#include "stdafx.h"
#include "gp.h"
#include "gp_Ax2d.h"
#include "gp_Ax22d.h"
#include "gp_Pnt2d.h"
#include "gp_Trsf2d.h"
#include "gp_Vec2d.h"
#include "gp_Hypr2d.h"


void gp_Hypr2d::Coefficients (double& A, 
	double& B, 
	double& C, 
	double& D, 
	double& E, 
	double& F) const 
{
	double DMin = minorRadius * minorRadius;
	double DMaj = majorRadius * majorRadius;
	if (DMin <= gp::Resolution() && DMaj <= gp::Resolution()) {
		A = B = C = D = E = F = 0.0;
	}
	else {
		gp_Trsf2d T;
		T.SetTransformation (pos.XAxis());
		double T11 = T.Value (1, 1);
		double T12 = T.Value (1, 2);
		double T13 = T.Value (1, 3);
		if (DMin <= gp::Resolution()) {
			A = T11 * T11;   B = T12 * T12;   C = T11 * T12;
			D = T11 * T13;   E = T12 * T13;   F = T13 * T13 - DMaj;
		}
		else {
			double T21 = T.Value (2, 1);
			double T22 = T.Value (2, 2);
			double T23 = T.Value (2, 3);
			A = (T11 * T11 / DMaj) - (T21 * T21 / DMin);
			B = (T12 * T12 / DMaj) - (T22 * T22 / DMin);
			C = (T11 * T12 / DMaj) - (T21 * T22 / DMin);
			D = (T11 * T13 / DMaj) - (T21 * T23 / DMin);
			E = (T12 * T13 / DMaj) - (T22 * T23 / DMin);
			F = (T13 * T13 / DMaj) - (T23 * T23 / DMin) - 1.0;
		}
	}
}

void gp_Hypr2d::Mirror (const gp_Pnt2d& P)
{ pos.Mirror(P); }

gp_Hypr2d gp_Hypr2d::Mirrored (const gp_Pnt2d& P) const
{
	gp_Hypr2d H = *this;
	H.pos.Mirror (P);
	return H; 
}

void gp_Hypr2d::Mirror (const gp_Ax2d& A)
{ pos.Mirror(A); }

gp_Hypr2d gp_Hypr2d::Mirrored (const gp_Ax2d& A) const
{
	gp_Hypr2d H = *this;
	H.pos.Mirror (A);
	return H; 
}


 gp_Hypr2d::gp_Hypr2d () :
majorRadius(DBL_MAX),
minorRadius(DBL_MAX)
{ }

 gp_Hypr2d::gp_Hypr2d (const gp_Ax22d& A, 
			     const double MajorRadius, 
			     const double MinorRadius) :  
			     pos(A), 
			     majorRadius(MajorRadius), 
			     minorRadius(MinorRadius)
{
  Standard_ConstructionError_Raise_if
    (MinorRadius < 0.0 || MajorRadius < 0.0,"");
}

 gp_Hypr2d::gp_Hypr2d (const gp_Ax2d& MajorAxis, 
		      const double MajorRadius, 
		      const double MinorRadius,
		      const bool Sense) :  
		      majorRadius(MajorRadius), 
		      minorRadius(MinorRadius) 
{ 
  pos = gp_Ax22d(MajorAxis,Sense); 
  Standard_ConstructionError_Raise_if
    (MinorRadius < 0.0 || MajorRadius < 0.0,"");
}

 void gp_Hypr2d::SetLocation (const gp_Pnt2d& P)
{ pos.SetLocation (P); }

 void gp_Hypr2d::SetMajorRadius (const double MajorRadius) 
{   
  Standard_ConstructionError_Raise_if(MajorRadius < 0.0,"");
  majorRadius = MajorRadius;
}

 void gp_Hypr2d::SetMinorRadius (const double MinorRadius) 
{ 
  Standard_ConstructionError_Raise_if(MinorRadius < 0.0,"");
  minorRadius = MinorRadius;
}

 void gp_Hypr2d::SetAxis (const gp_Ax22d& A) 
{ pos.SetAxis(A); }

 void gp_Hypr2d::SetXAxis (const gp_Ax2d& A) 
{ pos.SetXAxis(A); }

 void gp_Hypr2d::SetYAxis (const gp_Ax2d& A) 
{ pos.SetYAxis(A); }

 gp_Ax2d gp_Hypr2d::Asymptote1() const 
{
  Standard_ConstructionError_Raise_if (majorRadius <= gp::Resolution(), "");
  gp_Dir2d Vdir = pos.XDirection();
  gp_XY Coord1 (pos.YDirection().XY());
  gp_XY Coord2 = Coord1.Multiplied (minorRadius / majorRadius);
  Coord1.Add (Coord2);
  Vdir.SetXY (Coord1);
  return gp_Ax2d (pos.Location(), Vdir);
}

 gp_Ax2d gp_Hypr2d::Asymptote2() const {
  Standard_ConstructionError_Raise_if (majorRadius <= gp::Resolution(), "");
  gp_Vec2d Vdir = pos.XDirection();
  gp_XY  Coord1 (pos.YDirection().XY());
  gp_XY  Coord2 = Coord1.Multiplied (-minorRadius / majorRadius);
  Coord1.Add (Coord2);
  Vdir.SetXY (Coord1);
  return gp_Ax2d (pos.Location(), Vdir);
}

 gp_Hypr2d gp_Hypr2d::ConjugateBranch1() const 
{
  gp_Dir2d V (pos.YDirection());
  bool sign = (pos.XDirection().Crossed(pos.YDirection())) >= 0.0;
  return gp_Hypr2d (gp_Ax2d (pos.Location(),V), minorRadius, majorRadius,sign);
}

 gp_Hypr2d gp_Hypr2d::ConjugateBranch2() const 
{
  gp_Dir2d V (pos.YDirection().Reversed());
  bool sign = (pos.XDirection().Crossed(pos.YDirection())) >= 0.0;
  return gp_Hypr2d (gp_Ax2d(pos.Location(),V),minorRadius, majorRadius,sign);
}

 gp_Ax2d gp_Hypr2d::Directrix1() const 
{
  double E = Eccentricity();
  gp_XY Orig = pos.XDirection().XY();
  Orig.Multiply (majorRadius/E);
  Orig.Add (pos.Location().XY());
  return gp_Ax2d (gp_Pnt2d(Orig),gp_Dir2d (pos.YDirection()));
}

 gp_Ax2d gp_Hypr2d::Directrix2() const
{
  double E = Eccentricity();
  gp_XY Orig = pos.XDirection().XY();
  Orig.Multiply (Parameter()/E);
  Orig.Add (Focus1().XY());
  return gp_Ax2d (gp_Pnt2d(Orig),gp_Dir2d (pos.YDirection()));
}

 double gp_Hypr2d::Eccentricity() const 
{
  Standard_DomainError_Raise_if (majorRadius <= gp::Resolution(), "");
  return sqrt(majorRadius * majorRadius +
	      minorRadius * minorRadius) / majorRadius;
}

 double gp_Hypr2d::Focal() const 
{
  return 2.0 * sqrt (majorRadius * majorRadius +
		     minorRadius * minorRadius);
}

 gp_Pnt2d gp_Hypr2d::Focus1() const 
{
  double C = sqrt (majorRadius * majorRadius +
			  minorRadius * minorRadius);
  return gp_Pnt2d (pos.Location().X() + C * pos.XDirection().X(),
		   pos.Location().Y() + C * pos.XDirection().Y());
}

 gp_Pnt2d gp_Hypr2d::Focus2() const 
{
  double C = sqrt (majorRadius * majorRadius +
			  minorRadius * minorRadius);
  return gp_Pnt2d (pos.Location().X() - C * pos.XDirection().X(),
		   pos.Location().Y() - C * pos.XDirection().Y());
}

 const gp_Pnt2d& gp_Hypr2d::Location () const
{ return pos.Location(); }

   double gp_Hypr2d::MajorRadius() const
 { return majorRadius; }

   double gp_Hypr2d::MinorRadius() const
 { return minorRadius; }

 gp_Hypr2d gp_Hypr2d::OtherBranch() const 
{
  bool sign = (pos.XDirection().Crossed(pos.YDirection())) >= 0.0;
  return gp_Hypr2d (gp_Ax2d (pos.Location(),pos.XDirection().Reversed()),
		    majorRadius,minorRadius,sign);
}

 double gp_Hypr2d::Parameter() const 
{ 
  Standard_DomainError_Raise_if (majorRadius <= gp::Resolution(), "");
  return (minorRadius * minorRadius) / majorRadius;
}

   const gp_Ax22d& gp_Hypr2d::Axis () const
 { return pos; }

 gp_Ax2d gp_Hypr2d::XAxis () const 
{ return pos.XAxis(); }

 gp_Ax2d gp_Hypr2d::YAxis () const 
{ return pos.YAxis(); }

 void gp_Hypr2d::Reverse() 
{
  gp_Dir2d Temp = pos.YDirection ();
  Temp.Reverse ();
  pos.SetAxis(gp_Ax22d(pos.Location(),pos.XDirection(),Temp));
}

 gp_Hypr2d gp_Hypr2d::Reversed() const
{
  gp_Hypr2d H = *this;
  gp_Dir2d Temp = pos.YDirection ();
  Temp.Reverse ();
  H.pos.SetAxis(gp_Ax22d(pos.Location(),pos.XDirection(),Temp));
  return H;
}

 bool gp_Hypr2d::IsDirect() const
{ return (pos.XDirection().Crossed(pos.YDirection())) >= 0.0; }

 void gp_Hypr2d::Rotate (const gp_Pnt2d& P,
			       const double Ang)
{pos.Rotate (P,Ang);}

 gp_Hypr2d gp_Hypr2d::Rotated (const gp_Pnt2d& P,
				     const double Ang) const
{
  gp_Hypr2d H = *this;
  H.pos.Rotate (P, Ang);
  return H; 
}

 void gp_Hypr2d::Scale (const gp_Pnt2d& P,
			      const double S)
{ 
  majorRadius *= S;
  if (majorRadius < 0) majorRadius = - majorRadius;
  minorRadius *= S;
  if (minorRadius < 0) minorRadius = - minorRadius;
  pos.Scale(P, S);
}

 gp_Hypr2d gp_Hypr2d::Scaled (const gp_Pnt2d& P,
				    const double S) const
{
  gp_Hypr2d H = *this;
  H.majorRadius *= S;
  if (H.majorRadius < 0) H.majorRadius = - H.majorRadius;
  H.minorRadius *= S;
  if (H.minorRadius < 0) H.minorRadius = - H.minorRadius;
  H.pos.Scale(P, S);
  return H; 
}

 void gp_Hypr2d::Transform (const gp_Trsf2d& T)
{
  majorRadius *= T.ScaleFactor();
  if (majorRadius < 0) majorRadius = - majorRadius;
  minorRadius *= T.ScaleFactor();
  if (minorRadius < 0) minorRadius = - minorRadius;
  pos.Transform(T);
}

 gp_Hypr2d gp_Hypr2d::Transformed (const gp_Trsf2d& T) const
{
gp_Hypr2d H = *this;
H.majorRadius *= T.ScaleFactor();
if (H.majorRadius < 0) H.majorRadius = - H.majorRadius;
H.minorRadius *= T.ScaleFactor();
if (H.minorRadius < 0) H.minorRadius = - H.minorRadius;
H.pos.Transform(T);
return H;
}

 void gp_Hypr2d::Translate (const gp_Vec2d& V)
{ pos.Translate(V); }

 gp_Hypr2d gp_Hypr2d::Translated (const gp_Vec2d& V) const
{
  gp_Hypr2d H = *this;
  H.pos.Translate(V);
  return H; 
}

 void gp_Hypr2d::Translate (const gp_Pnt2d& P1,
				  const gp_Pnt2d& P2)
{
  pos.Translate(P1, P2);
}

 gp_Hypr2d gp_Hypr2d::Translated (const gp_Pnt2d& P1,
					const gp_Pnt2d& P2) const
{
  gp_Hypr2d H = *this;
  H.pos.Translate(P1, P2);
  return H; 
}

